home *** CD-ROM | disk | FTP | other *** search
/ Amiga Games Extra 1996 September / Amiga Games Extra CD-ROM 9-1996.iso / userbox / publicdomain / vim-4.2 / src / amiga.c < prev    next >
C/C++ Source or Header  |  1996-06-09  |  31KB  |  1,491 lines

  1. /* vi:set ts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved        by Bram Moolenaar
  4.  *
  5.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  6.  * Do ":help credits" in Vim to see a list of people who contributed.
  7.  */
  8.  
  9. /*
  10.  * amiga.c
  11.  *
  12.  * Amiga system-dependent routines.
  13.  */
  14.  
  15. #include "vim.h"
  16. #include "globals.h"
  17. #include "proto.h"
  18. #include "option.h"
  19.  
  20. #ifdef HAVE_FCNTL_H
  21. # include <fcntl.h>
  22. #endif
  23.  
  24. #undef TRUE             /* will be redefined by exec/types.h */
  25. #undef FALSE
  26.  
  27. #ifndef LATTICE
  28. # include <exec/types.h>
  29. # include <exec/exec.h>
  30. # include <libraries/dos.h>
  31. # include <libraries/dosextens.h>
  32. # include <intuition/intuition.h>
  33. #else
  34. # include <proto/dos.h>
  35. # include <libraries/dosextens.h>
  36. # include <proto/intuition.h>
  37. # include <proto/exec.h>
  38. #endif
  39.  
  40. #include <exec/memory.h>
  41.  
  42. #include <dos/dostags.h>            /* for 2.0 functions */
  43. #include <dos/dosasl.h>
  44.  
  45. #if defined(LATTICE) && !defined(SASC) && !defined(NO_ARP)
  46. # include <libraries/arp_pragmas.h>
  47. #endif
  48.  
  49. /*
  50.  * At this point TRUE and FALSE are defined as 1L and 0L, but we want 1 and 0.
  51.  */
  52. #undef    TRUE
  53. #define TRUE (1)
  54. #undef    FALSE
  55. #define FALSE (0)
  56.  
  57. #ifndef AZTEC_C
  58. static long dos_packet __ARGS((struct MsgPort *, long, long));
  59. #endif
  60. static int lock2name __ARGS((BPTR lock, char_u *buf, long    len));
  61. static struct FileInfoBlock *get_fib __ARGS((char_u *));
  62. static int sortcmp __ARGS((char **a, char **b));
  63.  
  64. static BPTR                raw_in = (BPTR)NULL;
  65. static BPTR                raw_out = (BPTR)NULL;
  66. static int                close_win = FALSE;    /* set if Vim opened the window */
  67.  
  68. struct IntuitionBase    *IntuitionBase = NULL;
  69. #ifndef NO_ARP
  70. struct ArpBase            *ArpBase = NULL;
  71. #endif
  72.  
  73. static struct Window    *wb_window;
  74. static char_u            *oldwindowtitle = NULL;
  75.  
  76. #ifndef NO_ARP
  77. int                        dos2 = FALSE;        /* Amiga DOS 2.0x or higher */
  78. #endif
  79. int                        size_set = FALSE;    /* set to TRUE if window size was set */
  80.  
  81.     void
  82. win_resize_on()
  83. {
  84.     OUTSTRN("\033[12{");
  85. }
  86.  
  87.     void
  88. win_resize_off()
  89. {
  90.     OUTSTRN("\033[12}");
  91. }
  92.  
  93.     void
  94. mch_write(p, len)
  95.     char_u    *p;
  96.     int        len;
  97. {
  98.     Write(raw_out, (char *)p, (long)len);
  99. }
  100.  
  101. /*
  102.  * mch_inchar(): low level input funcion.
  103.  * Get a characters from the keyboard.
  104.  * If time == 0 do not wait for characters.
  105.  * If time == n wait a short time for characters.
  106.  * If time == -1 wait forever for characters.
  107.  *
  108.  * Return number of characters read.
  109.  */
  110.     int
  111. mch_inchar(buf, maxlen, time)
  112.     char_u    *buf;
  113.     int        maxlen;
  114.     long    time;                /* milli seconds */
  115. {
  116.     int        len;
  117.     long    utime;
  118.     
  119.     if (time >= 0)
  120.     {
  121.         if (time == 0)
  122.             utime = 100L;            /* time = 0 causes problems in DOS 1.2 */
  123.         else
  124.             utime = time * 1000L;    /* convert from milli to micro secs */
  125.         if (WaitForChar(raw_in, utime) == 0)    /* no character available */
  126.             return 0;
  127.     }
  128.     else    /* time == -1 */
  129.     {
  130.     /*
  131.      * If there is no character available within 2 seconds (default)
  132.      * write the autoscript file to disk
  133.      */
  134.         if (WaitForChar(raw_in, p_ut * 1000L) == 0)
  135.             updatescript(0);
  136.     }
  137.  
  138.     for (;;)        /* repeat until we got a character */
  139.     {
  140.         len = Read(raw_in, (char *)buf, (long)maxlen);
  141.         if (len > 0)
  142.             return len;
  143.     }
  144. }
  145.  
  146. /*
  147.  * return non-zero if a character is available
  148.  */
  149.     int
  150. mch_char_avail()
  151. {
  152.     return (WaitForChar(raw_in, 100L) != 0);
  153. }
  154.  
  155.     long
  156. mch_avail_mem(special)
  157.     int        special;
  158. {
  159.     return (long)AvailMem(special ? (long)MEMF_CHIP : (long)MEMF_ANY);
  160. }
  161.  
  162.     void
  163. mch_delay(msec, ignoreinput)
  164.     long    msec;
  165.     int        ignoreinput;
  166. {
  167. #ifndef LATTICE            /* SAS declares void Delay(UNLONG) */
  168.     void            Delay __ARGS((long));
  169. #endif
  170.  
  171.     if (msec > 0)
  172.     {
  173.         if (ignoreinput)
  174.             Delay(msec / 20L);        /* Delay works with 20 msec intervals */
  175.         else
  176.             WaitForChar(raw_in, msec * 1000L);
  177.     }
  178. }
  179.  
  180. /*
  181.  * We have no job control, fake it by starting a new shell.
  182.  */
  183.     void
  184. mch_suspend()
  185. {
  186.     MSG_OUTSTR("new shell started\n");
  187.     (void)call_shell(NULL, SHELL_COOKED);
  188.     need_check_timestamps = TRUE;
  189. }
  190.  
  191. #define DOS_LIBRARY     ((UBYTE *) "dos.library")
  192.  
  193.     void
  194. mch_windinit()
  195. {
  196.     static char        intlibname[] = "intuition.library";
  197.  
  198. #ifdef AZTEC_C
  199.     Enable_Abort = 0;            /* disallow vim to be aborted */
  200. #endif
  201.     Columns = 80;
  202.     Rows = 24;
  203.  
  204.     /*
  205.      * Set input and output channels, unless we have opened our own window
  206.      */
  207.     if (raw_in == (BPTR)NULL)
  208.     {
  209.         raw_in = Input();
  210.         raw_out = Output();
  211.     }
  212.  
  213.     flushbuf();
  214.  
  215.     wb_window = NULL;
  216.     if ((IntuitionBase = (struct IntuitionBase *)OpenLibrary((UBYTE *)intlibname, 0L)) == NULL)
  217.     {
  218.         fprintf(stderr, "cannot open %s!?\n", intlibname);
  219.         mch_windexit(3);
  220.     }
  221.     (void)mch_get_winsize();
  222. }
  223.  
  224. #include <workbench/startup.h>
  225.  
  226. /*
  227.  * Check_win checks whether we have an interactive window.
  228.  * If not, a new window is opened with the newcli command.
  229.  * If we would open a window ourselves, the :sh and :! commands would not
  230.  * work properly (Why? probably because we are then running in a background
  231.  * CLI). This also is the best way to assure proper working in a next
  232.  * Workbench release.
  233.  *
  234.  * For the -e option (quickfix mode) and -x we open our own window and disable
  235.  * :sh. Otherwise the compiler would never know when editing is finished.
  236.  */
  237. #define BUF2SIZE 320        /* length of buffer for argument with complete path */
  238.  
  239.     int
  240. mch_check_win(argc, argv)
  241.     int argc;
  242.     char **argv;
  243. {
  244.     int                i;
  245.     BPTR            nilfh, fh;
  246.     char_u            buf1[20];
  247.     char_u            buf2[BUF2SIZE];
  248.     static char_u    *(constrings[3]) = {(char_u *)"con:0/0/662/210/",
  249.                                       (char_u *)"con:0/0/640/200/",
  250.                                       (char_u *)"con:0/0/320/200/"};
  251.     static char_u    winerr[] = "VIM: Can't open window!\n";
  252.     struct WBArg    *argp;
  253.     int                ac;
  254.     char            *av;
  255.     char_u            *device = NULL;
  256.     int                exitval = 4;
  257.     struct Library    *DosBase;
  258.     int                usewin = FALSE;
  259.  
  260. /*
  261.  * check if we are running under DOS 2.0x or higher
  262.  */
  263.     if (DosBase = OpenLibrary(DOS_LIBRARY, 37L))
  264.     {
  265.         CloseLibrary(DosBase);
  266. #ifndef NO_ARP
  267.         dos2 = TRUE;
  268. #endif
  269.     }
  270.     else            /* without arp functions we NEED 2.0 */
  271.     {
  272. #ifdef NO_ARP
  273.         fprintf(stderr, "Need Amigados version 2.04 or later\n");
  274.         exit(3);
  275. #else
  276.                     /* need arp functions for dos 1.x */
  277.         if (!(ArpBase = (struct ArpBase *) OpenLibrary((UBYTE *)ArpName, ArpVersion)))
  278.         {
  279.             fprintf(stderr, "Need %s version %ld\n", ArpName, ArpVersion);
  280.             exit(3);
  281.         }
  282. #endif
  283.     }
  284.  
  285. /*
  286.  * scan argv[] for the '-e', '-x' and '-d' arguments
  287.  */
  288.     for (i = 1; i < argc; ++i)
  289.         if (argv[i][0] == '-')
  290.         {
  291.             switch (argv[i][1])
  292.             {
  293.             case 'e':
  294.             case 'x':
  295.                 usewin = TRUE;
  296.                 break;
  297.  
  298.             case 'd':
  299.                 if (i < argc - 1)
  300.                     device = (char_u *)argv[i + 1];
  301.                 break;
  302.             }
  303.         }
  304.  
  305. /*
  306.  * If we were not started from workbench, do not have a '-d' argument and
  307.  * we have been started with an interactive window, use that window.
  308.  */
  309.     if (argc != 0 && device == NULL &&
  310.                             IsInteractive(Input()) && IsInteractive(Output()))
  311.         return OK;
  312.  
  313. /*
  314.  * If we are in quickfix mode, we open our own window. We can't use the
  315.  * newcli trick below, because the compiler would not know when we are finished.
  316.  * We do the same with the '-x' option, for mail, rn, etc.
  317.  */
  318.     if (usewin)
  319.     {
  320.         /*
  321.          * Try to open a window. First try the specified device.
  322.          * Then try a 24 line 80 column window.
  323.          * If that fails, try two smaller ones.
  324.          */
  325.         for (i = -1; i < 3; ++i)
  326.         {
  327.             if (i >= 0)
  328.                 device = constrings[i];
  329.             if (device && (raw_in = Open((UBYTE *)device, (long)MODE_NEWFILE)) != (BPTR)NULL)
  330.                 break;
  331.         }
  332.         if (raw_in == (BPTR)NULL)        /* all three failed */
  333.         {
  334.             fprintf(stderr, (char *)winerr);
  335.             goto exit;
  336.         }
  337.         raw_out = raw_in;
  338.         close_win = TRUE;
  339.         return OK;
  340.     }
  341.  
  342.     if ((nilfh = Open((UBYTE *)"NIL:", (long)MODE_NEWFILE)) == (BPTR)NULL)
  343.     {
  344.         fprintf(stderr, "Cannot open NIL:\n");
  345.         goto exit;
  346.     }
  347.  
  348.     /*
  349.      * make a unique name for the temp file (which we will not delete!)
  350.      */
  351.     sprintf((char *)buf1, "t:nc%ld", (char *)buf1);    /* nobody else is using our stack */
  352.     if ((fh = Open((UBYTE *)buf1, (long)MODE_NEWFILE)) == (BPTR)NULL)
  353.     {
  354.         fprintf(stderr, "Cannot create %s\n", (char *)buf1);
  355.         goto exit;
  356.     }
  357.     /*
  358.      * Write the command into the file, put quotes around the arguments that
  359.      * have a space in them.
  360.      */
  361.     if (argc == 0)        /* run from workbench */
  362.         ac = ((struct WBStartup *)argv)->sm_NumArgs;
  363.     else
  364.         ac = argc;
  365.     for (i = 0; i < ac; ++i)
  366.     {
  367.         if (argc == 0)
  368.         {
  369.             *buf2 = NUL;
  370.             argp = &(((struct WBStartup *)argv)->sm_ArgList[i]);
  371.             if (argp->wa_Lock)
  372.                 (void)lock2name(argp->wa_Lock, buf2, (long)(BUF2SIZE - 1));
  373. #ifndef NO_ARP
  374.             if (dos2)        /* use 2.0 function */
  375. #endif
  376.                 AddPart((UBYTE *)buf2, (UBYTE *)argp->wa_Name, (long)(BUF2SIZE - 1));
  377. #ifndef NO_ARP
  378.             else            /* use arp function */
  379.                 TackOn((char *)buf2, argp->wa_Name);
  380. #endif
  381.             av = (char *)buf2;
  382.         }
  383.         else
  384.             av = argv[i];
  385.  
  386.         if (av[0] == '-' && av[1] == 'd')        /* skip '-d' option */
  387.         {
  388.             ++i;
  389.             continue;
  390.         }
  391.         if (vim_strchr((char_u *)av, ' '))
  392.             Write(fh, "\"", 1L);
  393.         Write(fh, av, (long)strlen(av));
  394.         if (vim_strchr((char_u *)av, ' '))
  395.             Write(fh, "\"", 1L);
  396.         Write(fh, " ", 1L);
  397.     }
  398.     Write(fh, "\nendcli\n", 8L);
  399.     Close(fh);
  400.  
  401. /*
  402.  * Try to open a new cli in a window. If '-d' argument was given try to open
  403.  * the specified device. Then try a 24 line 80 column window.
  404.  * If that fails, try two smaller ones.
  405.  */
  406.     for (i = -1; i < 3; ++i)
  407.     {
  408.         if (i >= 0)
  409.             device = constrings[i];
  410.         else if (device == NULL)
  411.             continue;
  412.         sprintf((char *)buf2, "newcli <nil: >nil: %s from %s", (char *)device, (char *)buf1);
  413. #ifndef NO_ARP
  414.         if (dos2)
  415.         {
  416. #endif
  417.             if (!SystemTags((UBYTE *)buf2, SYS_UserShell, TRUE, TAG_DONE))
  418.                 break;
  419. #ifndef NO_ARP
  420.         }
  421.         else
  422.         {
  423.             if (Execute((UBYTE *)buf2, nilfh, nilfh))
  424.                 break;
  425.         }
  426. #endif
  427.     }
  428.     if (i == 3)        /* all three failed */
  429.     {
  430.         DeleteFile((UBYTE *)buf1);
  431.         fprintf(stderr, (char *)winerr);
  432.         goto exit;
  433.     }
  434.     exitval = 0;    /* The Execute succeeded: exit this program */
  435.  
  436. exit:
  437. #ifndef NO_ARP
  438.     if (ArpBase)
  439.         CloseLibrary((struct Library *) ArpBase);
  440. #endif
  441.     exit(exitval);
  442.     /* NOTREACHED */
  443.     return FAIL;
  444. }
  445.  
  446. /*
  447.  * Return OK if the input comes from a terminal, FAIL otherwise.
  448.  * We fake there is a window, because we can always open one!
  449.  */
  450.     int
  451. mch_check_input()
  452. {
  453.     return OK;
  454. }
  455.  
  456. /*
  457.  * fname_case(): Set the case of the filename, if it already exists.
  458.  *                 This will cause the filename to remain exactly the same.
  459.  */
  460.     void
  461. fname_case(name)
  462.     char_u    *name;
  463. {
  464.     register struct FileInfoBlock    *fib;
  465.     register size_t                    len;
  466.  
  467.     fib = get_fib(name);
  468.     if (fib != NULL)
  469.     {
  470.         len = STRLEN(name);
  471.         if (len == strlen(fib->fib_FileName))    /* safety check */
  472.             vim_memmove(name, fib->fib_FileName, len);
  473.         vim_free(fib);
  474.     }
  475. }
  476.  
  477. /*
  478.  * Get the FileInfoBlock for file "fname"
  479.  * The returned structure has to be free()d.
  480.  * Returns NULL on error.
  481.  */
  482.     static struct FileInfoBlock *
  483. get_fib(fname)
  484.     char_u *fname;
  485. {
  486.     register BPTR                    flock;
  487.     register struct FileInfoBlock    *fib;
  488.  
  489.     if (fname == NULL)        /* safety check */
  490.         return NULL;
  491.     fib = (struct FileInfoBlock *)malloc(sizeof(struct FileInfoBlock));
  492.     if (fib != NULL)
  493.     {
  494.         flock = Lock((UBYTE *)fname, (long)ACCESS_READ);
  495.         if (flock == (BPTR)NULL || !Examine(flock, fib))
  496.         {
  497.             vim_free(fib);    /* in case of an error the memory is freed here */
  498.             fib = NULL;
  499.         }
  500.         if (flock)
  501.             UnLock(flock);
  502.     }
  503.     return fib;
  504. }
  505.  
  506. /*
  507.  * set the title of our window
  508.  * icon name is not set
  509.  */
  510.     void
  511. mch_settitle(title, icon)
  512.     char_u    *title;
  513.     char_u    *icon;
  514. {
  515.     if (wb_window != NULL && title != NULL)
  516.         SetWindowTitles(wb_window, (UBYTE *)title, (UBYTE *)-1L);
  517. }
  518.  
  519. /*
  520.  * Restore the window/icon title.
  521.  * which is one of:
  522.  *    1  Just restore title
  523.  *  2  Just restore icon (which we don't have)
  524.  *    3  Restore title and icon (which we don't have)
  525.  */
  526.     void
  527. mch_restore_title(which)
  528.     int which;
  529. {
  530.     if (which & 1)
  531.         mch_settitle(oldwindowtitle, NULL);
  532. }
  533.  
  534.     int
  535. mch_can_restore_title()
  536. {
  537.     return (wb_window != NULL);
  538. }
  539.  
  540.     int
  541. mch_can_restore_icon()
  542. {
  543.     return FALSE;
  544. }
  545.  
  546. /*
  547.  * Insert user name in s[len].
  548.  */
  549.     int
  550. mch_get_user_name(s, len)
  551.     char_u    *s;
  552.     int        len;
  553. {
  554.     *s = NUL;
  555.     return FAIL;
  556. }
  557.  
  558. /*
  559.  * Insert host name is s[len].
  560.  */
  561.     void
  562. mch_get_host_name(s, len)
  563.     char_u    *s;
  564.     int        len;
  565. {
  566.     STRNCPY(s, "Amiga", len);
  567. }
  568.  
  569. /*
  570.  * return process ID
  571.  */
  572.     long
  573. mch_get_pid()
  574. {
  575.     return (long)0;
  576. }
  577.  
  578. /*
  579.  * Get name of current directory into buffer 'buf' of length 'len' bytes.
  580.  * Return OK for success, FAIL for failure.
  581.  */
  582.     int
  583. mch_dirname(buf, len)
  584.     char_u        *buf;
  585.     int            len;
  586. {
  587.     return FullName((char_u *)"", buf, len, FALSE);
  588. }
  589.  
  590. /*
  591.  * get absolute filename into buffer 'buf' of length 'len' bytes
  592.  *
  593.  * return FAIL for failure, OK otherwise
  594.  */
  595.     int
  596. FullName(fname, buf, len, force)
  597.     char_u        *fname, *buf;
  598.     int            len;
  599.     int            force;
  600. {
  601.     BPTR        l;
  602.     int            retval = FAIL;
  603.     int            i;
  604.  
  605.     *buf = NUL;
  606.     if (fname == NULL)    /* always fail */
  607.         return FAIL;
  608.  
  609.     if ((l = Lock((UBYTE *)fname, (long)ACCESS_READ)) != (BPTR)0)/* lock the file */
  610.     {
  611.         retval = lock2name(l, buf, (long)len);
  612.         UnLock(l);
  613.     }
  614.     else if (force || !isFullName(fname))        /* not a full path yet */
  615.     {
  616.         /*
  617.          * If cannot lock the file, try to lock the current directory and then
  618.          * concatenate the file name.  Works when file doesn't exist yet.
  619.          */
  620.         if ((l = Lock((UBYTE *)"", (long)ACCESS_READ)) != (BPTR)NULL) /* lock current dir */
  621.         {
  622.             retval = lock2name(l, buf, (long)len);
  623.             UnLock(l);
  624.             if (retval == OK)
  625.             {
  626.                 i = STRLEN(buf);
  627.                 if (i < len - 1 && (i == 0 || buf[i - 1] != ':'))
  628.                     buf[i++] = '/';
  629.                 STRNCPY(buf + i, fname, (len - i));    /* concatenate the fname */
  630.             }
  631.         }
  632.     }
  633.     if (retval == FAIL || *buf == 0 || *buf == ':')
  634.         STRCPY(buf, fname);    /* something failed; use the filename */
  635.     return retval;
  636. }
  637.  
  638. /*
  639.  * return TRUE is fname is an absolute path name
  640.  */
  641.     int
  642. isFullName(fname)
  643.     char_u        *fname;
  644. {
  645.     return (vim_strchr(fname, ':') != NULL);
  646. }
  647.  
  648. /*
  649.  * Get the full filename from a lock. Use 2.0 function if possible, because
  650.  * the arp function has more restrictions on the path length.
  651.  *
  652.  * return FAIL for failure, OK otherwise
  653.  */
  654.     static int
  655. lock2name(lock, buf, len)
  656.     BPTR    lock;
  657.     char_u    *buf;
  658.     long    len;
  659. {
  660. #ifndef NO_ARP
  661.     if (dos2)                /* use 2.0 function */
  662. #endif
  663.         return ((int)NameFromLock(lock, (UBYTE *)buf, len) ? OK : FAIL);
  664. #ifndef NO_ARP
  665.     else                /* use arp function */
  666.         return ((int)PathName(lock, (char *)buf, (long)(len/32)) ? OK : FAIL);
  667. #endif
  668. }
  669.  
  670. /*
  671.  * get file permissions for 'name'
  672.  */
  673.     long
  674. getperm(name)
  675.     char_u        *name;
  676. {
  677.     struct FileInfoBlock    *fib;
  678.     long                     retval = -1;
  679.  
  680.     fib = get_fib(name);
  681.     if (fib != NULL)
  682.     {
  683.         retval = fib->fib_Protection;
  684.         vim_free(fib);
  685.     }
  686.     return retval;
  687. }
  688.  
  689. /*
  690.  * set file permission for 'name' to 'perm'
  691.  *
  692.  * return FAIL for failure, OK otherwise
  693.  */
  694.     int
  695. setperm(name, perm)
  696.     char_u        *name;
  697.     long        perm;
  698. {
  699.     perm &= ~FIBF_ARCHIVE;                /* reset archived bit */
  700.     return (SetProtection((UBYTE *)name, (long)perm) ? OK : FAIL);
  701. }
  702.  
  703. /*
  704.  * return FALSE if "name" is not a directory
  705.  * return TRUE if "name" is a directory.
  706.  * return FALSE for error.
  707.  */
  708.     int
  709. mch_isdir(name)
  710.     char_u        *name;
  711. {
  712.     struct FileInfoBlock    *fib;
  713.     int                     retval = FALSE;
  714.  
  715.     fib = get_fib(name);
  716.     if (fib != NULL)
  717.     {
  718.         retval = ((fib->fib_DirEntryType >= 0) ? TRUE : FALSE);
  719.         vim_free(fib);
  720.     }
  721.     return retval;
  722. }
  723.  
  724. /*
  725.  * Careful: mch_windexit() may be called before mch_windinit()!
  726.  */
  727.     void
  728. mch_windexit(r)
  729.     int             r;
  730. {
  731.     if (raw_in)                        /* put terminal in 'normal' mode */
  732.     {
  733.         settmode(0);
  734.         stoptermcap();
  735.     }
  736.     if (raw_out)
  737.     {
  738.         if (term_console)
  739.         {
  740.             win_resize_off();        /* window resize events de-activated */
  741.             if (size_set)
  742.                 OUTSTR("\233t\233u");    /* reset window size (CSI t CSI u) */
  743.         }
  744.         flushbuf();
  745.     }
  746.  
  747.     mch_restore_title(3);            /* restore window title */
  748.  
  749.     ml_close_all(TRUE);                /* remove all memfiles */
  750.  
  751. #ifndef NO_ARP
  752.     if (ArpBase)
  753.         CloseLibrary((struct Library *) ArpBase);
  754. #endif
  755.     if (close_win)
  756.         Close(raw_in);
  757.     if (r)
  758.         printf("Vim exiting with %d\n", r);    /* somehow this makes :cq work!? */
  759.     exit(r);
  760. }
  761.  
  762. /*
  763.  * This is a routine for setting a given stream to raw or cooked mode on the
  764.  * Amiga . This is useful when you are using Lattice C to produce programs
  765.  * that want to read single characters with the "getch()" or "fgetc" call.
  766.  *
  767.  * Written : 18-Jun-87 By Chuck McManis.
  768.  */
  769.  
  770. #define MP(xx)    ((struct MsgPort *)((struct FileHandle *) (BADDR(xx)))->fh_Type)
  771.  
  772. /*
  773.  * Function mch_settmode() - Convert the specified file pointer to 'raw' or 'cooked'
  774.  * mode. This only works on TTY's.
  775.  *
  776.  * Raw: keeps DOS from translating keys for you, also (BIG WIN) it means
  777.  *        getch() will return immediately rather than wait for a return. You
  778.  *        lose editing features though.
  779.  *
  780.  * Cooked: This function returns the designate file pointer to it's normal,
  781.  *        wait for a <CR> mode. This is exactly like raw() except that
  782.  *        it sends a 0 to the console to make it back into a CON: from a RAW:
  783.  */
  784.     void
  785. mch_settmode(raw)
  786.     int            raw;
  787. {
  788.     if (dos_packet(MP(raw_in), (long)ACTION_SCREEN_MODE, raw ? -1L : 0L) == 0)
  789.         fprintf(stderr, "cannot change console mode ?!\n");
  790. }
  791.  
  792. /*
  793.  * set screen mode, always fails.
  794.  */
  795.     int
  796. mch_screenmode(arg)
  797.     char_u     *arg;
  798. {
  799.     EMSG("Screen mode setting not supported");
  800.     return FAIL;
  801. }
  802.  
  803. /*
  804.  * Code for this routine came from the following :
  805.  *
  806.  * ConPackets.c -  C. Scheppner, A. Finkel, P. Lindsay    CBM
  807.  *     DOS packet example
  808.  *     Requires 1.2
  809.  *
  810.  * Found on Fish Disk 56.
  811.  *
  812.  * Heavely modified by mool.
  813.  */
  814.  
  815. #include <devices/conunit.h>
  816.  
  817. /*
  818.  * try to get the real window size
  819.  * return FAIL for failure, OK otherwise
  820.  */
  821.     int
  822. mch_get_winsize()
  823. {
  824.     struct ConUnit    *conUnit;
  825.      char            id_a[sizeof(struct InfoData) + 3];
  826.     struct InfoData *id;
  827.  
  828.     if (!term_console)    /* not an amiga window */
  829.         return FAIL;
  830.  
  831.     /* insure longword alignment */
  832.      id = (struct InfoData *)(((long)id_a + 3L) & ~3L);
  833.  
  834.     /*
  835.      * Should make console aware of real window size, not the one we set.
  836.      * Unfortunately, under DOS 2.0x this redraws the window and it
  837.      * is rarely needed, so we skip it now, unless we changed the size.
  838.      */
  839.     if (size_set)
  840.         OUTSTR("\233t\233u");    /* CSI t CSI u */
  841.     flushbuf();
  842.  
  843.     if (dos_packet(MP(raw_out), (long)ACTION_DISK_INFO, ((ULONG) id) >> 2) == 0 ||
  844.                 (wb_window = (struct Window *)id->id_VolumeNode) == NULL)
  845.     {
  846.         /* it's not an amiga window, maybe aux device */
  847.         /* terminal type should be set */
  848.         term_console = FALSE;
  849.         return FAIL;
  850.     }
  851.     if (oldwindowtitle == NULL)
  852.         oldwindowtitle = (char_u *)wb_window->Title;
  853.     if (id->id_InUse == (BPTR)NULL)
  854.     {
  855.         fprintf(stderr, "mch_get_winsize: not a console??\n");
  856.         return FAIL;
  857.     }
  858.     conUnit = (struct ConUnit *) ((struct IOStdReq *) id->id_InUse)->io_Unit;
  859.  
  860.     /* get window size */
  861.     Rows = conUnit->cu_YMax + 1;
  862.     Columns = conUnit->cu_XMax + 1;
  863.     if (Rows < 0 || Rows > 200)     /* cannot be an amiga window */
  864.     {
  865.         Columns = 80;
  866.         Rows = 24;
  867.         term_console = FALSE;
  868.         return FAIL;
  869.     }
  870.     check_winsize();
  871.  
  872.     return OK;
  873. }
  874.  
  875. /*
  876.  * try to set the real window size
  877.  */
  878.     void
  879. mch_set_winsize()
  880. {
  881.     if (term_console)
  882.     {
  883.         size_set = TRUE;
  884.         outchar(CSI);
  885.         outnum((long)Rows);
  886.         outchar('t');
  887.         outchar(CSI);
  888.         outnum((long)Columns);
  889.         outchar('u');
  890.         flushbuf();
  891.     }
  892. }
  893.  
  894. #ifndef AZTEC_C
  895. /*
  896.  * Sendpacket.c
  897.  *
  898.  * An invaluable addition to your Amiga.lib file. This code sends a packet to
  899.  * the given message port. This makes working around DOS lots easier.
  900.  *
  901.  * Note, I didn't write this, those wonderful folks at CBM did. I do suggest
  902.  * however that you may wish to add it to Amiga.Lib, to do so, compile it and
  903.  * say 'oml lib:amiga.lib -r sendpacket.o'
  904.  */
  905.  
  906. /* #include <proto/exec.h> */
  907. /* #include <proto/dos.h> */
  908. #include <exec/memory.h>
  909.  
  910. /*
  911.  * Function - dos_packet written by Phil Lindsay, Carolyn Scheppner, and Andy
  912.  * Finkel. This function will send a packet of the given type to the Message
  913.  * Port supplied.
  914.  */
  915.  
  916.     static long
  917. dos_packet(pid, action, arg)
  918.     struct MsgPort *pid;    /* process indentifier ... (handlers message port) */
  919.     long            action, /* packet type ... (what you want handler to do)   */
  920.                     arg;    /* single argument */
  921. {
  922. # ifndef NO_ARP
  923.     struct MsgPort            *replyport;
  924.     struct StandardPacket    *packet;
  925.     long                    res1;
  926.  
  927.     if (dos2)
  928. # endif
  929.         return DoPkt(pid, action, arg, 0L, 0L, 0L, 0L);    /* use 2.0 function */
  930. # ifndef NO_ARP
  931.  
  932.     replyport = (struct MsgPort *) CreatePort(NULL, 0);    /* use arp function */
  933.     if (!replyport)
  934.         return (0);
  935.  
  936.     /* Allocate space for a packet, make it public and clear it */
  937.     packet = (struct StandardPacket *)
  938.         AllocMem((long) sizeof(struct StandardPacket), MEMF_PUBLIC | MEMF_CLEAR);
  939.     if (!packet) {
  940.         DeletePort(replyport);
  941.         return (0);
  942.     }
  943.     packet->sp_Msg.mn_Node.ln_Name = (char *) &(packet->sp_Pkt);
  944.     packet->sp_Pkt.dp_Link = &(packet->sp_Msg);
  945.     packet->sp_Pkt.dp_Port = replyport;
  946.     packet->sp_Pkt.dp_Type = action;
  947.     packet->sp_Pkt.dp_Arg1 = arg;
  948.  
  949.     PutMsg(pid, (struct Message *)packet);        /* send packet */
  950.  
  951.     WaitPort(replyport);
  952.     GetMsg(replyport);
  953.  
  954.     res1 = packet->sp_Pkt.dp_Res1;
  955.  
  956.     FreeMem(packet, (long) sizeof(struct StandardPacket));
  957.     DeletePort(replyport);
  958.  
  959.     return (res1);
  960. # endif
  961. }
  962. #endif
  963.  
  964. /*
  965.  * call shell, return FAIL for failure, OK otherwise
  966.  */
  967.     int
  968. call_shell(cmd, options)
  969.     char_u    *cmd;
  970.     int        options;        /* SHELL_FILTER if called by do_filter() */
  971.                             /* SHELL_COOKED if term needs cooked mode */
  972. {
  973.     BPTR    mydir;
  974.     int        x;
  975. #ifndef LATTICE
  976.     int        use_execute;
  977.     char_u    *shellcmd = NULL;
  978.     char_u    *shellarg;
  979. #endif
  980.     int    retval = OK;
  981.  
  982.     if (close_win)
  983.     {
  984.         /* if Vim opened a window: Executing a shell may cause crashes */
  985.         EMSG("Cannot execute shell with -e or -x option");
  986.         return FAIL;
  987.     }
  988.  
  989.     if (term_console)
  990.         win_resize_off();             /* window resize events de-activated */
  991.     flushbuf();
  992.  
  993.     if (options & SHELL_COOKED)
  994.         settmode(0);                 /* set to cooked mode */
  995.     mydir = Lock((UBYTE *)"", (long)ACCESS_READ);    /* remember current directory */
  996.  
  997. #ifdef LATTICE                        /* not tested very much */
  998.     if (cmd == NULL)
  999.     {
  1000. # ifndef NO_ARP
  1001.         if (dos2)
  1002. # endif
  1003.             x = SystemTags(p_sh, SYS_UserShell, TRUE, TAG_DONE);
  1004. # ifndef NO_ARP
  1005.         else
  1006.             x = Execute(p_sh, raw_in, raw_out);
  1007. # endif
  1008.     }
  1009.     else
  1010.     {
  1011. # ifndef NO_ARP
  1012.         if (dos2)
  1013. # endif
  1014.             x = SystemTags((char *)cmd, SYS_UserShell, TRUE, TAG_DONE);
  1015. # ifndef NO_ARP
  1016.         else
  1017.             x = Execute((char *)cmd, 0L, raw_out);
  1018. # endif
  1019.     }
  1020. # ifdef NO_ARP
  1021.     if (x < 0)
  1022. # else
  1023.     if ((dos2 && x < 0) || (!dos2 && !x))
  1024. # endif
  1025.     {
  1026.         MSG_OUTSTR("Cannot execute ");
  1027.         if (cmd == NULL)
  1028.         {
  1029.             MSG_OUTSTR("shell ");
  1030.             msg_outtrans(p_sh);
  1031.         }
  1032.         else
  1033.             msg_outtrans(cmd);
  1034.         msg_outchar('\n');
  1035.         retval = FAIL;
  1036.     }
  1037. # ifdef NO_ARP
  1038.     else if (x)
  1039. # else
  1040.     else if (!dos2 || x)
  1041. # endif
  1042.     {
  1043.         if (x = IoErr())
  1044.         {
  1045.             if (!expand_interactively)
  1046.             {
  1047.                 msg_outchar('\n');
  1048.                 msg_outnum(x);
  1049.                 MSG_OUTSTR(" returned\n");
  1050.             }
  1051.             retval = FAIL;
  1052.         }
  1053.     }
  1054. #else    /* !LATTICE */
  1055.     if (p_st >= 4 || (p_st >= 2 && options != SHELL_FILTER))
  1056.         use_execute = 1;
  1057.     else
  1058.         use_execute = 0;
  1059.     if (!use_execute)
  1060.     {
  1061.         /*
  1062.          * separate shell name from argument
  1063.          */
  1064.         shellcmd = strsave(p_sh);
  1065.         if (shellcmd == NULL)        /* out of memory, use Execute */
  1066.             use_execute = 1;
  1067.         else
  1068.         {
  1069.             shellarg = skiptowhite(shellcmd);    /* find start of arguments */
  1070.             if (*shellarg != NUL)
  1071.             {
  1072.                 *shellarg++ = NUL;
  1073.                 shellarg = skipwhite(shellarg);
  1074.             }
  1075.         }
  1076.     }
  1077.     if (cmd == NULL)
  1078.     {
  1079.         if (use_execute)
  1080.         {
  1081. # ifndef NO_ARP
  1082.             if (dos2)
  1083. # endif
  1084.                 x = SystemTags((UBYTE *)p_sh, SYS_UserShell, TRUE, TAG_DONE);
  1085. # ifndef NO_ARP
  1086.             else
  1087.                 x = !Execute((UBYTE *)p_sh, raw_in, raw_out);
  1088. # endif
  1089.         }
  1090.         else
  1091.             x = fexecl((char *)shellcmd, (char *)shellcmd, (char *)shellarg, NULL);
  1092.     }
  1093.     else if (use_execute)
  1094.     {
  1095. # ifndef NO_ARP
  1096.         if (dos2)
  1097. # endif
  1098.             x = SystemTags((UBYTE *)cmd, SYS_UserShell, TRUE, TAG_DONE);
  1099. # ifndef NO_ARP
  1100.         else
  1101.             x = !Execute((UBYTE *)cmd, 0L, raw_out);
  1102. # endif
  1103.     }
  1104.     else if (p_st & 1)
  1105.         x = fexecl((char *)shellcmd, (char *)shellcmd, (char *)shellarg, (char *)cmd, NULL);
  1106.     else
  1107.         x = fexecl((char *)shellcmd, (char *)shellcmd, (char *)shellarg, "-c", (char *)cmd, NULL);
  1108. # ifdef NO_ARP
  1109.     if (x < 0)
  1110. # else
  1111.     if ((dos2 && x < 0) || (!dos2 && x))
  1112. # endif
  1113.     {
  1114.         MSG_OUTSTR("Cannot execute ");
  1115.         if (use_execute)
  1116.         {
  1117.             if (cmd == NULL)
  1118.                 msg_outstr(p_sh);
  1119.             else
  1120.                 msg_outstr(cmd);
  1121.         }
  1122.         else
  1123.         {
  1124.             MSG_OUTSTR("shell ");
  1125.             msg_outstr(shellcmd);
  1126.         }
  1127.         msg_outchar('\n');
  1128.         retval = FAIL;
  1129.     }
  1130.     else
  1131.     {
  1132.         if (use_execute)
  1133.         {
  1134. # ifdef NO_ARP
  1135.             if (x)
  1136. # else
  1137.             if (!dos2 || x)
  1138. # endif
  1139.                 x = IoErr();
  1140.         }
  1141.         else
  1142.             x = wait();
  1143.         if (x)
  1144.         {
  1145.             if (!expand_interactively)
  1146.             {
  1147.                 msg_outchar('\n');
  1148.                 msg_outnum((long)x);
  1149.                 MSG_OUTSTR(" returned\n");
  1150.             }
  1151.             retval = FAIL;
  1152.         }
  1153.     }
  1154.     vim_free(shellcmd);
  1155. #endif    /* !LATTICE */
  1156.  
  1157.     if (mydir = CurrentDir(mydir))        /* make sure we stay in the same directory */
  1158.         UnLock(mydir);
  1159.     settmode(1);                         /* set to raw mode */
  1160.     resettitle();
  1161.     if (term_console)
  1162.         win_resize_on();                 /* window resize events activated */
  1163.     return retval;
  1164. }
  1165.  
  1166. /*
  1167.  * check for an "interrupt signal"
  1168.  * We only react to a CTRL-C, but also clear the other break signals to avoid
  1169.  * trouble with lattice-c programs.
  1170.  */
  1171.     void
  1172. mch_breakcheck()
  1173. {
  1174.    if (SetSignal(0L, (long)(SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D|SIGBREAKF_CTRL_E|SIGBREAKF_CTRL_F)) & SIGBREAKF_CTRL_C)
  1175.         got_int = TRUE;
  1176. }
  1177.  
  1178. /* this routine causes manx to use this Chk_Abort() rather than it's own */
  1179. /* otherwise it resets our ^C when doing any I/O (even when Enable_Abort */
  1180. /* is zero).  Since we want to check for our own ^C's                    */
  1181.  
  1182. #ifdef _DCC
  1183. #define Chk_Abort chkabort
  1184. #endif
  1185.  
  1186. #ifdef LATTICE
  1187. void __regargs __chkabort(void);
  1188.  
  1189. void __regargs __chkabort(void)
  1190. {}
  1191.  
  1192. #else
  1193.     long
  1194. Chk_Abort()
  1195. {
  1196.     return(0L);
  1197. }
  1198. #endif
  1199.  
  1200. /*
  1201.  * ExpandWildCards() - this code does wild-card pattern matching using the arp
  1202.  *                      routines. This is based on WildDemo2.c (found in arp1.1
  1203.  *                      distribution). That code's copyright follows :
  1204.  *-------------------------------------------------------------------------
  1205.  * WildDemo2.c - Search filesystem for patterns, and separate into directories
  1206.  *         and files, sorting each separately using DA lists.
  1207.  *
  1208.  * -+=SDB=+-
  1209.  *
  1210.  * Copyright (c) 1987, Scott Ballantyne
  1211.  * Use and abuse as you please.
  1212.  *
  1213.  * num_pat is number of input patterns
  1214.  * pat is array of pointers to input patterns
  1215.  * num_file is pointer to number of matched file names
  1216.  * file is pointer to array of pointers to matched file names
  1217.  * if file_only is TRUE we match only files, no dirs
  1218.  * if list_notfound is TRUE we include not-found entries (probably locked)
  1219.  * return OK for success, FAIL for error (you may loose some memory)
  1220.  *-------------------------------------------------------------------------
  1221.  */
  1222.  
  1223. /* #include <arpfunctions.h> */
  1224. extern void *malloc __ARGS((size_t)), *calloc __ARGS((size_t, size_t));
  1225. static int insfile __ARGS((char_u *, int));
  1226. static void freefiles __ARGS((void));
  1227.  
  1228. #define ANCHOR_BUF_SIZE (512)
  1229. #define ANCHOR_SIZE (sizeof(struct AnchorPath) + ANCHOR_BUF_SIZE)
  1230.  
  1231. /*
  1232.  * we use this structure to built a list of file names
  1233.  */
  1234. struct onefile
  1235. {
  1236.     struct onefile    *next;
  1237.     char_u            name[1];    /* really longer */
  1238. } *namelist = NULL;
  1239.  
  1240. /*
  1241.  * insert one file into the list of file names
  1242.  * return FAIL for failure
  1243.  * return OK for success
  1244.  */
  1245.     static int
  1246. insfile(name, isdir)
  1247.     char_u    *name;
  1248.     int        isdir;
  1249. {
  1250.     struct onefile *newp;
  1251.  
  1252.     newp = (struct onefile *)alloc((unsigned)(sizeof(struct onefile) +
  1253.                                                     STRLEN(name) + isdir));
  1254.     if (newp == NULL)
  1255.         return FAIL;
  1256.     STRCPY(&(newp->name[0]), name);
  1257.     if (isdir)
  1258.         STRCAT(&(newp->name[0]), "/");
  1259.     newp->next = namelist;
  1260.     namelist = newp;
  1261.     return OK;
  1262. }
  1263.  
  1264. /*
  1265.  * free a whole list of file names
  1266.  */
  1267.     static void
  1268. freefiles()
  1269. {
  1270.     struct onefile *p;
  1271.  
  1272.     while (namelist)
  1273.     {
  1274.         p = namelist->next;
  1275.         vim_free(namelist);
  1276.         namelist = p;
  1277.     }
  1278. }
  1279.  
  1280.     static int
  1281. sortcmp(a, b)
  1282.     char **a, **b;
  1283. {
  1284.     return strcmp(*a, *b);
  1285. }
  1286.  
  1287.     int
  1288. ExpandWildCards(num_pat, pat, num_file, file, files_only, list_notfound)
  1289.     int             num_pat;
  1290.     char_u          **pat;
  1291.     int            *num_file;
  1292.     char_u         ***file;
  1293.     int            files_only;
  1294.     int            list_notfound;
  1295. {
  1296.     int                     i;
  1297.     int                        cur_pat;
  1298.     struct AnchorPath        *Anchor;
  1299.     int                        domatchend = FALSE;
  1300.     LONG                    Result;
  1301.     struct onefile            *p;
  1302.     char_u                    *errmsg = NULL;
  1303.     char_u                    *starbuf, *sp, *dp;
  1304.     int                        foundone;
  1305.     int                        prev_num_file = 0;
  1306.     char_u                    **file_new;
  1307.  
  1308.     *num_file = 0;
  1309.     *file = (char_u **)"";
  1310.  
  1311.     /* Get our AnchorBase */
  1312.     Anchor = (struct AnchorPath *) calloc((size_t)1, (size_t)ANCHOR_SIZE);
  1313.     if (Anchor == NULL)
  1314.         goto OUT_OF_MEMORY;
  1315.     Anchor->ap_Strlen = ANCHOR_BUF_SIZE;    /* ap_Length not supported anymore */
  1316. #ifdef APF_DODOT
  1317.     Anchor->ap_Flags = APF_DODOT | APF_DOWILD;        /* allow '.' for current dir */
  1318. #else
  1319.     Anchor->ap_Flags = APF_DoDot | APF_DoWild;        /* allow '.' for current dir */
  1320. #endif
  1321.  
  1322.     for (cur_pat = 0; cur_pat < num_pat; cur_pat++)
  1323.     {
  1324. #ifndef NO_ARP
  1325.         if (dos2)
  1326.         {
  1327. #endif
  1328.                 /* hack to replace '*' by '#?' */
  1329.             starbuf = alloc((unsigned)(2 * STRLEN(pat[cur_pat]) + 1));
  1330.             if (starbuf == NULL)
  1331.                 goto OUT_OF_MEMORY;
  1332.             for (sp = pat[cur_pat], dp = starbuf; *sp; ++sp)
  1333.             {
  1334.                 if (*sp == '*')
  1335.                 {
  1336.                     *dp++ = '#';
  1337.                     *dp++ = '?';
  1338.                 }
  1339.                 else
  1340.                     *dp++ = *sp;
  1341.             }
  1342.             *dp = NUL;
  1343.             Result = MatchFirst((UBYTE *)starbuf, Anchor);
  1344.             vim_free(starbuf);
  1345. #ifndef NO_ARP
  1346.         }
  1347.         else
  1348.             Result = FindFirst((char *)pat[cur_pat], Anchor);
  1349. #endif
  1350.         domatchend = TRUE;
  1351.         foundone = FALSE;
  1352.         while (Result == 0)
  1353.         {
  1354.             if (!files_only || Anchor->ap_Info.fib_DirEntryType < 0)
  1355.             {
  1356.                 (*num_file)++;
  1357.                 if (insfile((char_u *)Anchor->ap_Buf, Anchor->ap_Info.fib_DirEntryType >= 0) == FAIL)
  1358.                 {
  1359. OUT_OF_MEMORY:
  1360.                     errmsg = (char_u *)"Out of memory";
  1361.                     goto Return;
  1362.                 }
  1363.                 foundone = TRUE;
  1364.             }
  1365. #ifndef NO_ARP
  1366.             if (dos2)
  1367. #endif
  1368.                 Result = MatchNext(Anchor);
  1369. #ifndef NO_ARP
  1370.             else
  1371.                 Result = FindNext(Anchor);
  1372. #endif
  1373.         }
  1374.         if (Result == ERROR_BUFFER_OVERFLOW)
  1375.         {
  1376.             errmsg = (char_u *)"ANCHOR_BUF_SIZE too small.";
  1377.             goto Return;
  1378.         }
  1379.         if (!foundone)
  1380.         {
  1381.             if (list_notfound)    /* put object with error in list */
  1382.             {
  1383.                 (*num_file)++;
  1384.                 if (insfile(pat[cur_pat], FALSE) == FAIL)
  1385.                     goto OUT_OF_MEMORY;
  1386.             }
  1387.             else if (Result != ERROR_OBJECT_NOT_FOUND && Result != ERROR_NO_MORE_ENTRIES)
  1388.             {
  1389.                 errmsg = (char_u *)"I/O ERROR";
  1390.                 goto Return;
  1391.             }
  1392.         }
  1393. #ifndef NO_ARP
  1394.         if (dos2)
  1395. #endif
  1396.             MatchEnd(Anchor);
  1397. #ifndef NO_ARP
  1398.         else
  1399.             FreeAnchorChain(Anchor);
  1400. #endif
  1401.         domatchend = FALSE;
  1402.         /*
  1403.          * Sort the files for this pattern.
  1404.          * Move the already found files to the newly allocated array.
  1405.          */
  1406.         if (namelist)
  1407.         {
  1408.             file_new = (char_u **) malloc(sizeof(char_u *) * *num_file);
  1409.             if (file_new == NULL)
  1410.                 goto OUT_OF_MEMORY;
  1411.             if (prev_num_file)
  1412.             {
  1413.                 for (i = 0; i < prev_num_file; ++i)
  1414.                     file_new[i] = (*file)[i];
  1415.                 vim_free(*file);
  1416.             }
  1417.             *file = file_new;
  1418.  
  1419.             p = namelist;
  1420.             for (i = *num_file - 1; p; p = p->next, --i)
  1421.             {
  1422.                 (*file)[i] = (char_u *) malloc(STRLEN(p->name) + 1);
  1423.                 if ((*file)[i] == NULL)
  1424.                     goto OUT_OF_MEMORY;
  1425.                 STRCPY((*file)[i], p->name);
  1426.             }
  1427.             qsort((void *)&((*file)[prev_num_file]),
  1428.                                            (size_t)(*num_file - prev_num_file),
  1429.                                                      sizeof(char_u *), sortcmp);
  1430.             prev_num_file = *num_file;
  1431.             freefiles();
  1432.         }
  1433.     }
  1434.  
  1435. Return:
  1436.     if (domatchend)
  1437.     {
  1438. #ifndef NO_ARP
  1439.         if (dos2)
  1440. #endif
  1441.             MatchEnd(Anchor);
  1442. #ifndef NO_ARP
  1443.         else
  1444.             FreeAnchorChain(Anchor);
  1445. #endif
  1446.     }
  1447.     if (Anchor)
  1448.         vim_free(Anchor);
  1449.     freefiles();
  1450.     if (errmsg)
  1451.     {
  1452.         emsg(errmsg);
  1453.         *num_file = 0;
  1454.         return FAIL;
  1455.     }
  1456.     return OK;
  1457. }
  1458.  
  1459.     int
  1460. mch_has_wildcard(p)
  1461.     char_u *p;
  1462. {
  1463.     for ( ; *p; ++p)
  1464.         if (vim_strchr((char_u *)"*?[(~#", *p) != NULL)
  1465.             return TRUE;
  1466.     return FALSE;
  1467. }
  1468.  
  1469. /*
  1470.  * With 2.0 support for reading local environment variables
  1471.  * Careful: uses IObuff!
  1472.  */
  1473.     char_u *
  1474. vim_getenv(var)
  1475.     char_u *var;
  1476. {
  1477.     int len;
  1478.  
  1479. #ifndef NO_ARP
  1480.     if (!dos2)
  1481.         return (char_u *)getenv((char *)var);
  1482. #endif
  1483.  
  1484.     len = GetVar((UBYTE *)var, (UBYTE *)IObuff, (long)(IOSIZE - 1), (long)0);
  1485.  
  1486.     if (len == -1)
  1487.         return NULL;
  1488.     else
  1489.         return IObuff;
  1490. }
  1491.